let activeEffect = null
// let shouldTrack = false
// let effectStack = []
const targetMap = new WeakMap()


export function effect(fn, options = {}) {
  // effect 嵌套，通过队列管理
  const effectFn = () => {
    try {
      activeEffect = effectFn
      // fn 执行的时候，内部读取响应式数据的时候，就能在 get 配置里读取到 activeEffect
      return fn()
    } finally {
      activeEffect = null
    }
  }

  // 没有配置 lazy 直接执行
  if (!options.lazy) {
    effectFn()
  }

  effectFn.scheduler = options.scheduler // 控制函数执行的时机，watchEffect 会用到
  return effectFn
}

/**
 * 把 effect 函数注册到依赖地图
 * @param {Object} target 
 * @param {String} type 
 * @param {String|Number} key 
 */
export function track(target, type, key) {
  // console.log(`触发 track -> target: ${target.constructor.name} type:${type} key:${key}`)

  // 存储结构
  // targetMap
  // { 
  //   target1: { // depsMap
  //     key1: [ effect1, effect2 ] // Set 回调函数集合
  //   }
  // }

  // 先基于 target 找到对应的 dep
  // 如果是第一次的话，那么就需要初始化

  let depsMap = targetMap.get(target)
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map())) // 初始化 depsMap
  }
  let deps = depsMap.get(key)
  if (!deps) {
    deps = new Set()
  }
  if (!deps.has(activeEffect) && activeEffect) {
    deps.add(activeEffect) // 防止重复注册
  }
  depsMap.set(key, deps)
}

/**
 * 把所有注册的 effect 函数挨个执行
 * @param {Object} target 
 * @param {String} type 
 * @param {String|Number} key 
 * @returns 
 */
export function trigger(target, type, key) {
  // console.log(`触发 trigger -> target: ${target.constructor.name} type:${type} key:${key}`)
  
  // 从 targetMap 中找到触发的函数，执行他
  const depsMap = targetMap.get(target)
  if (!depsMap) {
    return // 没找到依赖
  }

  const deps = depsMap.get(key)
  if (!deps) {
    return
  }

  deps.forEach((effectFn) => {
    if (effectFn.scheduler) {
      effectFn.scheduler()
    } else {
      effectFn()
    }
  })
}